<?php
	/*
	*   D3Sql Class v1.1.16
	* ============================================================
	* Kodlayan: Tufan Barış YILDIRIM & Savaş YILDIRIM
	* Website : http://www.tufyta.com & www.savasyildirim.com
	* ===================Versiyon Notları=========================
	*  v1.1.16  Savaş
	* =========
	* -- sutun_template ve aktif_sutunlar  sql() fonksiyonunda boşaltıldı
	*  v1.1.15
	* ========  01.11.2009
	* -- Dizi Aktarımındaki Hata Gösterimi Kaldırıldı.
	*  v1.1.14
	* ========
	* -- Jump() özelliği eklendi. mysql_data_seek görevi görüyor.
	* -- Plugin_Yeri Fonksiyonunda Değişiklşik yapıldı (Plugin Önce var mı diye kontrol eklendi.)
	*  v1.1.13
	* ========
	* -- Plugin Desteği eklendi
	* -- plugin_ekle ile fonksiyonlarınızı dahil edebilrisiniz.
	* -- Birden Fazla Grid yapılabilmesi için Gridden sonra DataSource Free kodu kaldırıldı
	*  v1.1.12
	* ======== 07.10.2009
	* -- Gridi içine alan <div> kaldırıldı.
	* -- mysql dataseti boşaltmak için Free() Fonksiyonu eklendi.
	* -- template fonksiyonu  sütun dizisi kullaılınca sadece dizideki sütunları replace edecek şekilde ayarlandı
	*  v1.1.11
	* =======  03.10.2009 
	* -- Template Fonksiyonu için artık Dizi yazmak gerekmicek. bunun tüm sutunlar için {$sutun_adi} kullanımı yapılabilecek
	* -- Bazı fonksiyonlarda iyileştirmeler yapıldı.
	* -- İşi biten değişkenler Unset() edildi.
	* -- Fonksiyon Sonucunu Fonksiyon ismiyle çağırma özelliği eklendi ileri sürümlerde {$sonuc} kullanımı kaldırılacak. 
	* v1.1.1
	* ======  23.09.2009
	* -- Template ile Sütun Başlangıcı Fonksiyondan sonraya alındı (Artık Satırlar için de Fonksiyon kullanılabilecek Her Satır için sınıf değişkenleri ile oynanabilecek.)
	* -- OnlyRead propertyler düzenlendi.
	* -- Protected Fonksiyonlar Duzenlendi.
	* -- hatalar htmlspecialchars() fonksiyonundan geçirildi
	* v1.1.0
	* ======
	* -- totalTime() Fonksiyonu Eklendi . Bağlantıdan İtibaren geçen microsaniyelik zamanı yazar.
	* -- sqlCount Property Eklendi . Toplam Sorgu sayısını yazar.
	* -- debug Mode Eklendi.  debug='ON' durumunda her Sorgudan Sonra Toplam Microsaniyeyi etkilenen satır sayısını ve Sorguyu gosterir.
	* v1.0.9
	* ======
	* -- query() fonksiyonu eklendi. Artık sınıf olarak dönüyor. $db->query()->say()  $db->query()->grid();  gibi kullanılabilecek
	* -- Baglan() Fonksiyonuna return link Eklendi. İkinci Sınıf Oluşturulmadan Yeni Bir Bağlantı yapılabilecek
	* -- Satır Sonu unutulan </tr> eklendi.
	* v1.0.8
	* =======
	* -- ConClone() Fonksiyonu Eklendi. var Olan bir Sınıftan Aynı bağlantı Değerlerinde başka bir sınıf turetmenize yarar.(İç İçe Gridlerde Aynı Sınıf Sonsuz Döngüye Neden Oluyordu.)
	* v1.0.7
	* =======
	* -- baslik_ozellikleri() Fonksiyonu Eklendi (Sütün Başlıklarına Ek özellikler verilebilecek)
	* -- insertten sonraki son autoincreament değerini alabilmek için sonid() fonksiyonu yazıldı
	* -- eko() Fonksiyonu değiştirildi ilk sutünun artık değeri olarak dönüyor
	* v.1.0.6
	* =======
	* -- Gridte sonuç bulunamayınca yapılan tag eksikliği giderildi.
	* -- Link Kontrolu kaldırıldı. Default $this->link kullanıldı
	* -- Diğer Gereksiz if kontrollerinden arındırıldı. Stabilizeyşın :)
	* v1.0.5
	* ======
	* -- Update_Array Fonksiyonu Yazıldı (insert_array) ile aynı mantıkta kolaylık sağlıyor.
	* -- Joker Fonksiyon Eko() Eklendi (: 
	* v1.0.4
	* ======
	* -- Ard arda Oluşturulan Gridlerin Birleştirilmesindeki Sorun Giderildi.
	* -- Başlıklarda TH yerine TD  kullanıldı.
	* v1.0.3
	* ======
	* -- Şartlı Template güçlendirildi  artık dahil ettiğiniz fonksiyonun sonucunu da templatte {$sonuc}  olarak kullanabilirsiniz.
	* -- Insert array Fonksiyonundaki Hata Düzeltildi (Değer Yerine de Sütun Adını Atıyordu.)
	* -- Gridden Sonraki Getir() sorunu giderildi (data_seek).
	* -- Otomatik Hata Gösterim Ayarı Eklendi $db->hata_goster
	* v1.0.2
	* ======
	* -- Dar Gelir Tufana dar Gelir (: 22"  bile dar gelir :P
	* -- Sutun_Templatei icad etmem guzel oldu :P
	* -- Sutuna template Mantığında değişkenlik ve düzenlenebilirliğin yanınnda şartlı template uygulaması da yaptım kikiki (:
	* -- Dışardan Tanımladığınız bir Fonksiyonu Gride Dahil edip her satır için ayrı çalıştırabilirsiniz.
	* -- pek kullanışlı olmasa bile tablo ozellikleri ve stil eklendi.
	* -- array insert fonksiyonu da eklendi daha kolay ve hatasız insert sorguları yapabilirsiniz.(tek satır tabi (:)
	* -- Sütun Pasif Edebilme Birden fazla gridi aynı Data Source ile ekrana basabilme eklendi.
	* -- Sütun Başlıkları Büyük Eksiklikti o da eklendi (: Sutun başlıklarınız bir dizi vererek değiştirebilirsiniz
	* -- Bunlarla yetinmiyosanız aferin yetinmeyin zaten ben de boyle bırakacak değilim devamı gelecek.
	* v1.0.1
	* ======
	* -- Grid Fonksiyonu eklendi.
	* -- Grid bu kadar basit bırakılamazdı Sutun_linkleme özelliği eklendi listeleme işlemleri daha kolay oldu.
	* v1.0
	* ======
	* -- Hemen hemen her programlamada ihtiyacımız olan tabloları eziyet olmaktan çıkarmaya karar verdik vesselam..
	* -- Multi-Connect . Query. Fetch . Error  gibi mysql in olmazlarını toplayıp bir sınıf yaptık.
	* */
	class D3Sql{

		var $sonhata,$sonsql,$sonquery,$tablo_baslik,$grid_footer;
		var $aktif_sutunlar               =array();
		var $sutun_adlari                 =array();
		var $tum_hatalar                  =array(); 
		var $style                        =array(
			"thead" =>  "thead",
			"row1"  =>  "row1",
			"row2"  =>  "row2",
		);
		var $tablo_ozellikleri            = array(
			"class" =>  "sortable",
			"id"    =>  "sortable_tablo"
		);
		var $hata_goster                  = True;
		var $debug                        = 'OFF'; 
		protected $dbhost,$dbuser,$dbpass,$dbname,$link,$sqlCount=0,$mTime;
		protected $baslik_ozellikleri     = array();
		protected $sutun_templates        = array();
		protected $plugins                = array();
		private $hata_charset             = 'UTF-8';

		/**
		* Veritabanı Bağlantı Fonksiyonu
		* 
		* @param mixed $dbhost Veritabanı Sunucu Adresi
		* @param mixed $dbuser Veritabanı Kullanıcı Adı
		* @param mixed $dbpass Veritabanı Şifresi
		*/
		function baglan($dbhost,$dbuser,$dbpass) 
		{
			$mictime=explode(' ',microtime());
			$this->mTime=(double)$mictime[0]+(double)$mictime[1];
			$this->dbhost = $dbhost;
			$this->dbuser = $dbuser;
			$this->dbpass = $dbpass;

			if($connectMysql = mysql_connect($this->dbhost,$this->dbuser,$this->dbpass))
			{
			  $this->link = $connectMysql;
			  return $this->link;       
			}
			else
			{
				$this->hata($this->dbhost.' Sunucusuna Bağlanırken Hata Oluştu <hr>'.$this->mysql_hata());
				die();
			}
			
		}

		/**
		* VeriTabanı Seçme Fonksiyonu
		* 
		* @param mixed $db İşlem Yapmak istediğiniz Veritabanı Adı
		*/

		function dbsec($db)
		{
			$db = $this->pluging_yeri('before_dbsec',$db);
			$this->dbname = (string)$db;
			if(mysql_select_db($this->dbname,$this->link))
			{
				$this->pluging_yeri('after_dbsec');
				return $this;
			}
			else
			{
				die('BAGLANTI HATASI!');
			}

		}
		/**
		* Aynı bağlantıyı Tekrar Sağlayarak Yeni Sınıf Oluşturmanıza Yarar. | v1.0.8
		* 
		* @param mixed $Class
		*/
		function ConClone($Class){
			$this->pluging_yeri('before_conclone');
			$this->baglan($Class->dbhost,$Class->dbuser,$Class->dbpass);
			$this->dbsec($Class->dbname); 
			$this->pluging_yeri('after_conclone');  
		}
		/**
		* Execute Fonksiyonu
		* 
		* @param mixed $sql Sql Cümlesi
		* @return resource
		*/
		function sql($sql) {

			$this->aktif_sutunlar=array();
			$this->sutun_templates=array();

			$this->sonsql=(string)$sql=$this->pluging_yeri('before_sql',$sql);
			$query=@mysql_query($this->sonsql,$this->link) OR $this->hata($this->sonsql.'  Cümlesi Sorgulanırken Hata Oluştu<hr>'.$this->mysql_hata($this->mysql_hata()));
			$this->sqlCount++;
			if ($this->debug=='ON') {
				$this->pluging_yeri('debug_insql');
				echo '<div class="well"><b>Sorgu:</b> <br /> '.str_replace("'","\\'",$sql).' <br /> <div class="alert-success"><b>Toplam :</b> '.$this->totalTime().' Saniye'.($this->etkilenen()>0 ? ' Etkilenen Satir : '.$this->etkilenen() : null).'</div></div>';
			}
			return $this->sonquery=$query;
		}

		/**
		* Sınıf Olarak Dönen Execute Fonksiyonu (v1.0.9)
		* 
		* @param mixed $sql Sql Cümlesi
		* @return class
		*/
		function query($sql) {
			$this->sql($sql);
			return $this;
		}
		/**
		*  Mysql_Fetch_Assoc
		*  @return array
		*/
		function getir(){
			$row =  @mysql_fetch_assoc(func_num_args()>0 ? func_get_arg(0):$this->sonquery);  
			//TODO : uyarı!! bu tüm sorguların tüm satırlarında çalışacağı için gereksiz bir  döngü olacaktır! ilk fırsatta tüm tarih formatları düzeltilip buradan kaldırılmalı
			if($row)
			{
				foreach($row as &$data)
				{
					if(preg_match('/^\d{4}-\d\d-\d\d(?P<saat> \d\d:\d\d:\d\d)?$/',$data = trim($data),$matches))
					{
						if(isset($matches['saat']))
							$data = date('d.m.Y H:i:s',strtotime($data));
						else
						{
							$data = date('d.m.Y',strtotime($data));
						}
					}
				}
			}

			return $row;
		}

		function fetch_all($sql,$filter = null)
		{
			$rows = array();
			if($query = $this->sql($sql))
			{
				while($row = $this->getir($query))
				{
					if($filter !== null && is_callable($filter))
						$filter($row);
					$rows[] = $row;
				}
			}
			return $rows;
		}

		/**
		*  Mysql_Fetch_Row
		*  @return array
		*/
		function rowgetir(){
			return @mysql_fetch_row(func_num_args()>0 ? func_get_arg(0):$this->sonquery);   
		}

		/**
		* İstediğiniz Sütun için Şablon mantığı ile şekil vereiblirsiniz.
		* 
		* @param mixed $sutun_adi Uygulamak istediğiniz Sütun
		* @param mixed $template  Sütuna Uygulamak istediğiniz şablon
		* @param mixed $degisecek_sutunlar
		*/
		function sutun_template($sutun_adi,$template,$degisecek_sutunlar=NULL) {
			$this->sutun_templates[$sutun_adi]= func_num_args()>3 ? array($template,$degisecek_sutunlar,func_get_arg(3)):array($template,$degisecek_sutunlar);
		}
		/**
		* Sütün Başlıkları için En Özellikler
		* 
		* @param mixed $sutun_adi  Etkilenmesini İstediğiniz Başlık Sütünunun Adı
		* @param mixed $ozellik_dizisi özellik dizisi
		*/

		function baslik_ozellikleri($sutun_adi,$ozellik_dizisi){
			$this->baslik_ozellikleri[$sutun_adi]=$ozellik_dizisi;
		}
		/**
		* En Son Sorguladığınız Cümleyi tanımladığınız şablonlara göre Tablo haline getirir.
		* @return sring
		*/          
		function grid()
		{
			$baslik_ozellikleri = null;
			$tablo_ozellikleri = null;
			
			$sinirli = count($this->aktif_sutunlar)>0;
			foreach ($this->tablo_ozellikleri AS $anahtar=>$deger) 
			{
				$tablo_ozellikleri .=' '.$anahtar.'="'.$deger.'"';
			}

			$this->grid=$this->pluging_yeri('before_grid',''); 
			$this->grid.='<table'.$tablo_ozellikleri.'>'."\n".$this->tablo_baslik."\n"; 

			$resource=func_num_args()>0 ? func_get_arg(0) :$this->sonquery;

			if (!is_resource($resource) OR get_resource_type($resource)!="mysql result") {
				$this->hata('Gride Dökmek İstediğiniz Değişken Bir mysql datasource değil.'); 
			}else {
				if ($this->say()<1) {
					$this->pluging_yeri('on_norows');
					$this->grid.='<tr><td class="sonuc_yok">Sonuç Yok.!</td></tr>';
				} else {

					$this->jump(0,$resource);

					$baslik=$this->getir($resource);
					$this->grid.='<tr class="'.$this->style['thead'].'">';
					foreach ($baslik AS $sutun_adi=>$data) {


						if (!$sinirli OR (in_array($sutun_adi,$this->aktif_sutunlar))) {
							if (in_array($sutun_adi,array_keys($this->baslik_ozellikleri))) {
								foreach ($this->baslik_ozellikleri[$sutun_adi] AS $ozellik_adi=>$ozellik_degeri){
									$baslik_ozellikleri[$sutun_adi].=" $ozellik_adi=\"$ozellik_degeri\"";   
								}
								unset($ozellik_adi,$ozellik_degeri);

							}
							$this->grid.='<td'.$baslik_ozellikleri[$sutun_adi].'>';
							array_key_exists($sutun_adi,$this->sutun_adlari) ? $sutun_adi=$this->sutun_adlari[$sutun_adi] : $sutun_adi=$sutun_adi;
							$this->grid.=$this->pluging_yeri('sutun_adi',$sutun_adi);  
							$this->grid.='</td>';
							unset($sutun_adi);

						}

					}
					$this->grid.='</tr>'."\n";
					$this->jump(0,$resource);
					while ($data=$this->getir($resource)) {
						$sutunlar = null;  
						foreach ($data As $sutun=>$icerik) {
							$this->grid_sutun=$data;
							if (array_key_exists($sutun,$this->sutun_templates)) {
								$gridtemp=$this->sutun_templates[$sutun];   
								$kullanilan_func_sonucu=@call_user_func($gridtemp[2],$data);// or $this->hata($gridtemp[2].' Adlı Fonksiyonunuzda Bir Sorun Var ..! Bir Değer Döndürmuyo Olabilir  Bkz. Return: ');

								if (count($gridtemp)==2 OR $kullanilan_func_sonucu){

									$tmp=$gridtemp[0];
									$tmp=str_replace('{$sonuc}',$kullanilan_func_sonucu,$tmp);

									if (is_array($gridtemp[1])) {
										foreach ($gridtemp[1] AS $num=>$sutun_name) {

											$tmp=str_replace('{$'.($num+1).'}',$data[$sutun_name],$tmp);
											$tmp=str_replace('{$'.$sutun_name.'}',$data[$sutun_name],$tmp);
										}

									}else {
										$tmp=str_replace('{$1}',$data[$gridtemp[1]],$tmp);   
										$tmp=str_replace('{$'.$gridtemp[1].'}',$data[$gridtemp[1]],$tmp); 

										foreach ($data AS $sutun_adi=>$sutun_degeri) {
											$tmp=str_replace('{$'.($sutun_adi).'}',$this->grid_sutun[$sutun_adi],$tmp);   
										}

									}

									$icerik=$tmp;

								} 
							}

							if (!$sinirli OR in_array($sutun,$this->aktif_sutunlar)) {    

								$sutunlar.='<td>';  
								$sutunlar.=$icerik;  
								$sutunlar.='</td>';  

							}   

						}

						$this->grid.='<tr class="'.$this->style['row1'].'" onmouseover="this.className=\''.$this->style['row2'].'\'" onmouseout="this.className=\''.$this->style['row1'].'\'">';
						$this->grid.=$sutunlar; unset($sutunlar);
						$this->grid.='</tr>'."\n";  
					}

				}
			}
			$this->grid.=$this->grid_footer."\n";
			$this->grid.='</table>'."\n";
			$this->jump(0,$resource);
			return  $this->pluging_yeri('after_grid',$this->grid);
		}
		/**
		* Ek olarak sınıfta çalıştırmak istediklerinizi plugin mantığı ile yerini yazarak çalıştırabilirsiniz.
		* 
		* @param mixed $plugin_yeri
		* @param mixed $function_adi
		*/
		function plugin_ekle($plugin_yeri,$function_adi){
			$this->plugins[$plugin_yeri][]=$function_adi;
			return $this;
		}
		/**
		* Sınıf İçinde Plugin Çalıştırmaya Yarar.
		* @param mixed $plugin_yeri
		*/
		protected function pluging_yeri($plugin_yeri,$Etkilenecek=NULL){
			if(in_array($plugin_yeri,$this->plugins)){
				if(count($this->plugins[$plugin_yeri])>0){
					foreach($this->plugins[$plugin_yeri] As $FuncName){
						$Etkilenecek=@call_user_func($FuncName,$Etkilenecek);
					}
				}
			}
			return $Etkilenecek;  
		}
		/**
		* Mysql Fetch Object Methodu ile Datasetten Objeler Döner
		* @return Array 
		*/
		function obje_getir(){
			return @mysql_fetch_object(func_num_args()>0 ? func_get_arg(0):$this->sonquery); 
		}
		/**
		* Kaçış karakterlerinden arındırma fonksiyonu
		* 
		* @param mixed $string
		* @return string
		*/
		function escape($string){
			if (is_array($string)){

				foreach ($string as $anum=>$adata) {

					$escaped[$anum]=@mysql_real_escape_string($adata);
				}   

			}
			else {

				$escaped=@mysql_real_escape_string($string);
			}

			return $escaped;

		}
		/**
		* Mysql_NumRows Metodu
		* @return int
		*/
		function say($query = NuLL) {
			if($query)
			{             
				return @mysql_numrows($query);
			}
			else
			{
				return @mysql_numrows($this->sonquery);
			}

		}
		/**
		* Select Yaparken eko adını verdiğiniz sutünun değerini yazar
		* Örnek : Select adi eko from isimler where id='1'
		* 
		* @param resource $sql
		*/
		function eko($sql){
			$sql=$this->sql($sql);
			$row=$this->rowgetir();
			return $row[0];
		}
		/**
		* Insert into işlemini Kolay ve hatasız yapabilmek için.
		* 
		* @param mixed $tablo  Tablo Adı
		* @param mixed $dizi   Insert Dizisi
		* @return resource     Dataset
		*/
		function insert_array($tablo,$dizi) {

			$sutunlar=array_keys($this->escape($dizi));
			$degerleri=array_values($this->escape($dizi));
			$sutun=implode(',',$sutunlar);

			//buna bir çözüm bu tufy!
			foreach($degerleri as &$d)
			{
				if($d != 'NOW()')
				{
					$d = "'{$d}'";
				}
			}

			$deger=implode(',',$degerleri);


			return  $this->sql('INSERT INTO '.$tablo.' ('.$sutun.') VALUES ('.$deger.')');

		}
		/**
		* Update işlemini Kolay ve hatasız yapabilmek için.
		* 
		* @param mixed $tablo Tablo adı
		* @param mixed $dizi  Update Dizisi
		* @param mixed $Where Varsa şart
		* @return resource
		*/
		function update_array($tablo,$dizi,$Where=False){

			foreach ($dizi As $Field=>$Data){
				$Update .=$Field."='".$Data."'";
			}

			$UpdateSql="UPDATE ".$tablo." SET ".$Update;

			if ($Where){
				$UpdateSql .=" WHERE ".$Where;  
			}

			return $this->sql($UpdateSql);

		}
		/**
		* Son Insert Sorgusundan Sonraki AutoIncreament Değeri
		* @return int
		*/
		function sonid(){
			return @mysql_insert_id($this->link);
		}
		/**
		* 
		*/
		function Free(){
			@mysql_free_result(func_num_args()>0 ? func_get_arg(0):$this->sonquery);
			return $this;
		}
		/**
		* Mysql bağlantısını kapatır
		* @return Boolean
		*/
		function kop() {
			return @mysql_close($this->link);
		}
		/**
		* Mysql Hatası Olarak Döner
		* @return String
		*/
		function mysql_hata() {
			return @mysql_error($this->link).' Hata No : '.$this->hata_no(); 

		}  
		/**
		* En Son Alınan Mysql hata numarası.
		* @return ErrCode
		*/
		function hata_no(){
			return @mysql_errno($this->link);

		}
		/**
		* Ekrana Basılan hataların karaktersetini Duzenler
		* 
		* @param mixed $charset
		*/
		function hata_charset($charset) {
			$charset ? $this->hata_charset=$charset :  $this->hata_charset;
			return $this;
		}

		/**
		* mysql_data_seek görevi görür datasourceda gitmek istediğiniz satıra numarsıyla ulaşabiliriz.
		* 
		* @param mixed $Rownum
		*/
		function jump($Rownum,$Resource=False){
			@mysql_data_seek($Resource?$Resource:$this->sonquery,$Rownum);
			return $this;
		}
		/**
		* Sorgudan Dönen ya da Etkilenen Satır Sayısı Döndürür
		*  @return int
		*/
		function etkilenen(){
			return @mysql_affected_rows($this->link);
		}
		/**
		* Hata Ekler
		* 
		* @param mixed $hatametni
		*/
		protected function hata($hatametni){


			// $this->sonhata = '<div style="background:#ffcccc;color:#d00000;border:1px solid;font-weight: 700;padding:10px;font-size:13px;text-align:Center;">'.str_replace('HRR','<hr>',htmlspecialchars(str_replace('<hr>','HRR',$hatametni))).'<br><center>Yardım İçin : <a href="index.php?p=yardim">Tıklayın</a></center></div>';
			$back = debug_backtrace();
			$this->sonhata = 
			'<div style="background:#ffcccc;position:absoulte;padding:5px">
			<pre>' . $hatametni .'
			' . $back[1]['file'] . ' on line ' . $back[1]['line'] . '
			</pre>
			</div>';

			if (function_exists('iconv')) 
				$this->sonhata = iconv('UTF-8',$this->hata_charset,$this->sonhata);

			$this->tum_hatalar[] = $this->sonhata;

			if ($this->hata_goster)
				echo $this->sonhata;

		}
		/**
		* Nesne Oluşturulduğu Andan itibaren geçen zamanı saniye cinsinden verir X.XX
		* @return float
		*/
		function totalTime()
		{
			$micTime = explode(' ',microtime());
			$endTime = (double)$micTime[0]+(double)$micTime[1];
			return round($endTime-$this->mTime,3);
		}
		/**
		* Nesne Oluşturulduğu andan itibaren yapılan sorgulama sayısı olarak döner
		* @return integer
		*/
		function sqlCount()
		{
			return $this->sqlCount;
		}   

	}
?>